"use strict";
var data = {
    count: 1
};
var target = null;
var targetStack = [];
function pushTarget(watchTarget) {
    if (watchTarget) {
        targetStack.push(watchTarget);
        target = watchTarget;
    }
}
function popTarget() {
    targetStack.pop();
    target = targetStack[targetStack.length - 1];
}
var Observe = /** @class */ (function () {
    function Observe(value) {
        this.value = value;
        if (Object.prototype.toString.call(this.value).slice(8, -1) === 'object') {
            this.walk();
        }
        else {
            //  rewrite Array method
        }
    }
    Observe.prototype.walk = function () {
        observe(this.value);
    };
    return Observe;
}());
function observe(obj) {
    if (typeof obj !== 'object') {
        return false;
    }
    Object.keys(obj).forEach(function (key) {
        defineReactive(obj, key);
    });
}
function defineReactive(obj, key) {
    var val = obj[key];
    var dep = new Dep();
    Reflect.defineProperty(obj, key, {
        get: function () {
            target && dep.depend(target);
            return val;
        },
        set: function (newVal) {
            if (newVal != val) {
                val = newVal;
                dep.notify();
            }
        }
    });
}
var Dep = /** @class */ (function () {
    function Dep() {
        this.subs = [];
    }
    //  依赖收集
    Dep.prototype.depend = function (target) {
        this.subs.push(target);
    };
    //  通知更新
    Dep.prototype.notify = function () {
        this.subs.forEach(function (watcher) { return watcher.update(); });
    };
    return Dep;
}());
var Watcher = /** @class */ (function () {
    function Watcher(updateFn) {
        this.updateFn = updateFn;
        pushTarget(this);
        this.update();
        popTarget();
    }
    Watcher.prototype.update = function () {
        this.updateFn && this.updateFn();
    };
    return Watcher;
}());
var ob = new Observe(data);
new Watcher(function () {
    console.log('render');
});
